# 工作流批量操作服务
import logging
from typing import Dict, List, Optional, Any
from django.contrib.auth.models import User
from django.utils import timezone
from django.db import transaction
from django.db.models import Q
from datetime import datetime, timedelta
import json

from .models_workflow import WorkflowTemplate, WorkflowInstance, WorkflowStepTask
from .workflow_engine import WorkflowEngine
from .notification_service import notification_service

logger = logging.getLogger(__name__)


class WorkflowBatchOperations:
    """工作流批量操作服务"""
    
    def __init__(self):
        self.workflow_engine = WorkflowEngine()
    
    def batch_start_instances(self, instance_ids: List[int], operator: User) -> Dict:
        """批量启动工作流实例"""
        
        results = {
            'success_count': 0,
            'failed_count': 0,
            'errors': [],
            'results': []
        }
        
        try:
            instances = WorkflowInstance.objects.filter(
                id__in=instance_ids,
                status='pending'
            )
            
            for instance in instances:
                try:
                    success = self.workflow_engine.start_workflow(instance.id, operator)
                    
                    if success:
                        results['success_count'] += 1
                        results['results'].append({
                            'instance_id': instance.id,
                            'instance_name': instance.instance_name,
                            'status': 'success'
                        })
                    else:
                        results['failed_count'] += 1
                        results['errors'].append(f"启动实例 {instance.instance_name} 失败")
                        results['results'].append({
                            'instance_id': instance.id,
                            'instance_name': instance.instance_name,
                            'status': 'failed',
                            'error': '启动失败'
                        })
                        
                except Exception as e:
                    error_msg = f"启动实例 {instance.instance_name} 失败: {str(e)}"
                    results['errors'].append(error_msg)
                    results['failed_count'] += 1
                    results['results'].append({
                        'instance_id': instance.id,
                        'instance_name': instance.instance_name,
                        'status': 'failed',
                        'error': str(e)
                    })
                    logger.error(error_msg)
            
            # 发送批量操作通知
            if results['success_count'] > 0:
                notification_service.send_notification(
                    users=[operator],
                    title="批量启动工作流完成",
                    message=f"成功启动 {results['success_count']} 个工作流实例，失败 {results['failed_count']} 个",
                    channels=['system']
                )
            
            return results
            
        except Exception as e:
            logger.error(f"批量启动工作流失败: {e}")
            results['errors'].append(f"批量操作失败: {str(e)}")
            return results
    
    def batch_cancel_instances(self, instance_ids: List[int], operator: User, reason: str = '') -> Dict:
        """批量取消工作流实例"""
        
        results = {
            'success_count': 0,
            'failed_count': 0,
            'errors': [],
            'results': []
        }
        
        try:
            instances = WorkflowInstance.objects.filter(
                id__in=instance_ids,
                status__in=['pending', 'running']
            )
            
            for instance in instances:
                try:
                    instance.cancel(reason or f"批量取消 by {operator.username}")
                    
                    results['success_count'] += 1
                    results['results'].append({
                        'instance_id': instance.id,
                        'instance_name': instance.instance_name,
                        'status': 'success'
                    })
                    
                except Exception as e:
                    error_msg = f"取消实例 {instance.instance_name} 失败: {str(e)}"
                    results['errors'].append(error_msg)
                    results['failed_count'] += 1
                    results['results'].append({
                        'instance_id': instance.id,
                        'instance_name': instance.instance_name,
                        'status': 'failed',
                        'error': str(e)
                    })
                    logger.error(error_msg)
            
            return results
            
        except Exception as e:
            logger.error(f"批量取消工作流失败: {e}")
            results['errors'].append(f"批量操作失败: {str(e)}")
            return results
    
    def batch_reassign_tasks(self, task_ids: List[int], new_assignee: User, operator: User) -> Dict:
        """批量重新分配任务"""
        
        results = {
            'success_count': 0,
            'failed_count': 0,
            'errors': [],
            'results': []
        }
        
        try:
            tasks = WorkflowStepTask.objects.filter(
                id__in=task_ids,
                status='pending'
            )
            
            for task in tasks:
                try:
                    old_assignee = task.assignee
                    task.assign_to(new_assignee)
                    
                    # 发送重新分配通知
                    notification_service.send_notification(
                        users=[new_assignee],
                        title=f"任务重新分配: {task.step_name}",
                        message=f"任务已从 {old_assignee.username if old_assignee else '未分配'} 重新分配给您",
                        channels=['system', 'email'],
                        action_url=f"/assets/workflow/tasks/{task.id}/"
                    )
                    
                    results['success_count'] += 1
                    results['results'].append({
                        'task_id': task.id,
                        'task_name': task.step_name,
                        'status': 'success'
                    })
                    
                except Exception as e:
                    error_msg = f"重新分配任务 {task.step_name} 失败: {str(e)}"
                    results['errors'].append(error_msg)
                    results['failed_count'] += 1
                    results['results'].append({
                        'task_id': task.id,
                        'task_name': task.step_name,
                        'status': 'failed',
                        'error': str(e)
                    })
                    logger.error(error_msg)
            
            return results
            
        except Exception as e:
            logger.error(f"批量重新分配任务失败: {e}")
            results['errors'].append(f"批量操作失败: {str(e)}")
            return results
    
    def batch_approve_tasks(self, task_ids: List[int], operator: User, comments: str = '') -> Dict:
        """批量批准任务"""
        
        results = {
            'success_count': 0,
            'failed_count': 0,
            'errors': [],
            'results': []
        }
        
        try:
            tasks = WorkflowStepTask.objects.filter(
                id__in=task_ids,
                status='pending'
            )
            
            for task in tasks:
                try:
                    # 检查权限
                    if task.assignee != operator and not operator.is_superuser:
                        results['failed_count'] += 1
                        results['errors'].append(f"无权限批准任务: {task.step_name}")
                        results['results'].append({
                            'task_id': task.id,
                            'task_name': task.step_name,
                            'status': 'failed',
                            'error': '无权限'
                        })
                        continue
                    
                    success = self.workflow_engine.complete_manual_task(
                        task_id=task.id,
                        operator=operator,
                        action='approve',
                        comments=comments or '批量批准'
                    )
                    
                    if success:
                        results['success_count'] += 1
                        results['results'].append({
                            'task_id': task.id,
                            'task_name': task.step_name,
                            'status': 'success'
                        })
                    else:
                        results['failed_count'] += 1
                        results['errors'].append(f"批准任务 {task.step_name} 失败")
                        results['results'].append({
                            'task_id': task.id,
                            'task_name': task.step_name,
                            'status': 'failed',
                            'error': '批准失败'
                        })
                    
                except Exception as e:
                    error_msg = f"批准任务 {task.step_name} 失败: {str(e)}"
                    results['errors'].append(error_msg)
                    results['failed_count'] += 1
                    results['results'].append({
                        'task_id': task.id,
                        'task_name': task.step_name,
                        'status': 'failed',
                        'error': str(e)
                    })
                    logger.error(error_msg)
            
            return results
            
        except Exception as e:
            logger.error(f"批量批准任务失败: {e}")
            results['errors'].append(f"批量操作失败: {str(e)}")
            return results
    
    def batch_reject_tasks(self, task_ids: List[int], operator: User, comments: str = '') -> Dict:
        """批量拒绝任务"""
        
        results = {
            'success_count': 0,
            'failed_count': 0,
            'errors': [],
            'results': []
        }
        
        try:
            tasks = WorkflowStepTask.objects.filter(
                id__in=task_ids,
                status='pending'
            )
            
            for task in tasks:
                try:
                    # 检查权限
                    if task.assignee != operator and not operator.is_superuser:
                        results['failed_count'] += 1
                        results['errors'].append(f"无权限拒绝任务: {task.step_name}")
                        results['results'].append({
                            'task_id': task.id,
                            'task_name': task.step_name,
                            'status': 'failed',
                            'error': '无权限'
                        })
                        continue
                    
                    success = self.workflow_engine.complete_manual_task(
                        task_id=task.id,
                        operator=operator,
                        action='reject',
                        comments=comments or '批量拒绝'
                    )
                    
                    if success:
                        results['success_count'] += 1
                        results['results'].append({
                            'task_id': task.id,
                            'task_name': task.step_name,
                            'status': 'success'
                        })
                    else:
                        results['failed_count'] += 1
                        results['errors'].append(f"拒绝任务 {task.step_name} 失败")
                        results['results'].append({
                            'task_id': task.id,
                            'task_name': task.step_name,
                            'status': 'failed',
                            'error': '拒绝失败'
                        })
                    
                except Exception as e:
                    error_msg = f"拒绝任务 {task.step_name} 失败: {str(e)}"
                    results['errors'].append(error_msg)
                    results['failed_count'] += 1
                    results['results'].append({
                        'task_id': task.id,
                        'task_name': task.step_name,
                        'status': 'failed',
                        'error': str(e)
                    })
                    logger.error(error_msg)
            
            return results
            
        except Exception as e:
            logger.error(f"批量拒绝任务失败: {e}")
            results['errors'].append(f"批量操作失败: {str(e)}")
            return results
    
    def batch_update_instance_data(self, instance_ids: List[int], update_data: Dict, operator: User) -> Dict:
        """批量更新工作流实例数据"""
        
        results = {
            'success_count': 0,
            'failed_count': 0,
            'errors': [],
            'results': []
        }
        
        try:
            instances = WorkflowInstance.objects.filter(id__in=instance_ids)
            
            for instance in instances:
                try:
                    # 更新工作流数据
                    for key, value in update_data.items():
                        instance.workflow_data[key] = value
                    
                    instance.save()
                    
                    results['success_count'] += 1
                    results['results'].append({
                        'instance_id': instance.id,
                        'instance_name': instance.instance_name,
                        'status': 'success'
                    })
                    
                except Exception as e:
                    error_msg = f"更新实例 {instance.instance_name} 数据失败: {str(e)}"
                    results['errors'].append(error_msg)
                    results['failed_count'] += 1
                    results['results'].append({
                        'instance_id': instance.id,
                        'instance_name': instance.instance_name,
                        'status': 'failed',
                        'error': str(e)
                    })
                    logger.error(error_msg)
            
            return results
            
        except Exception as e:
            logger.error(f"批量更新实例数据失败: {e}")
            results['errors'].append(f"批量操作失败: {str(e)}")
            return results
    
    def batch_export_instances(self, instance_ids: List[int], export_format: str = 'json') -> Dict:
        """批量导出工作流实例"""
        
        try:
            instances = WorkflowInstance.objects.filter(
                id__in=instance_ids
            ).select_related('template', 'created_by').prefetch_related('step_tasks', 'history_records')
            
            export_data = []
            
            for instance in instances:
                instance_data = {
                    'id': instance.id,
                    'instance_name': instance.instance_name,
                    'template_name': instance.template.name,
                    'status': instance.status,
                    'created_at': instance.created_at.isoformat(),
                    'created_by': instance.created_by.username,
                    'workflow_data': instance.workflow_data,
                    'steps': []
                }
                
                # 添加步骤信息
                for task in instance.step_tasks.all():
                    step_data = {
                        'step_id': task.step_id,
                        'step_name': task.step_name,
                        'step_type': task.step_type,
                        'status': task.status,
                        'assignee': task.assignee.username if task.assignee else None,
                        'created_at': task.created_at.isoformat(),
                        'completed_at': task.completed_at.isoformat() if task.completed_at else None,
                        'comments': task.comments,
                        'result_data': task.result_data
                    }
                    instance_data['steps'].append(step_data)
                
                export_data.append(instance_data)
            
            return {
                'success': True,
                'data': export_data,
                'count': len(export_data),
                'format': export_format
            }
            
        except Exception as e:
            logger.error(f"批量导出实例失败: {e}")
            return {
                'success': False,
                'error': str(e)
            }
    
    def batch_delete_instances(self, instance_ids: List[int], operator: User, force: bool = False) -> Dict:
        """批量删除工作流实例"""
        
        results = {
            'success_count': 0,
            'failed_count': 0,
            'errors': [],
            'results': []
        }
        
        try:
            instances = WorkflowInstance.objects.filter(id__in=instance_ids)
            
            for instance in instances:
                try:
                    # 检查是否可以删除
                    if not force and instance.status in ['running']:
                        results['failed_count'] += 1
                        results['errors'].append(f"实例 {instance.instance_name} 正在运行，无法删除")
                        results['results'].append({
                            'instance_id': instance.id,
                            'instance_name': instance.instance_name,
                            'status': 'failed',
                            'error': '实例正在运行'
                        })
                        continue
                    
                    # 删除相关数据
                    instance.step_tasks.all().delete()
                    instance.history_records.all().delete()
                    instance.delete()
                    
                    results['success_count'] += 1
                    results['results'].append({
                        'instance_id': instance.id,
                        'instance_name': instance.instance_name,
                        'status': 'success'
                    })
                    
                except Exception as e:
                    error_msg = f"删除实例 {instance.instance_name} 失败: {str(e)}"
                    results['errors'].append(error_msg)
                    results['failed_count'] += 1
                    results['results'].append({
                        'instance_id': instance.id,
                        'instance_name': instance.instance_name,
                        'status': 'failed',
                        'error': str(e)
                    })
                    logger.error(error_msg)
            
            return results
            
        except Exception as e:
            logger.error(f"批量删除实例失败: {e}")
            results['errors'].append(f"批量操作失败: {str(e)}")
            return results
    
    def get_batch_operation_status(self, operation_id: str) -> Dict:
        """获取批量操作状态（用于异步操作）"""
        
        # 这里可以实现基于Redis或数据库的操作状态跟踪
        # 简化实现，返回默认状态
        return {
            'operation_id': operation_id,
            'status': 'completed',
            'progress': 100,
            'message': '操作已完成'
        }
    
    def schedule_batch_operation(self, operation_type: str, params: Dict, operator: User) -> str:
        """调度批量操作（异步执行）"""
        
        # 生成操作ID
        operation_id = f"{operation_type}_{timezone.now().strftime('%Y%m%d_%H%M%S')}_{operator.id}"
        
        # 这里可以使用Celery等任务队列来异步执行批量操作
        # 简化实现，直接执行
        try:
            if operation_type == 'start_instances':
                result = self.batch_start_instances(params['instance_ids'], operator)
            elif operation_type == 'cancel_instances':
                result = self.batch_cancel_instances(params['instance_ids'], operator, params.get('reason', ''))
            elif operation_type == 'reassign_tasks':
                new_assignee = User.objects.get(id=params['new_assignee_id'])
                result = self.batch_reassign_tasks(params['task_ids'], new_assignee, operator)
            elif operation_type == 'approve_tasks':
                result = self.batch_approve_tasks(params['task_ids'], operator, params.get('comments', ''))
            elif operation_type == 'reject_tasks':
                result = self.batch_reject_tasks(params['task_ids'], operator, params.get('comments', ''))
            else:
                raise ValueError(f"不支持的操作类型: {operation_type}")
            
            # 记录操作结果
            logger.info(f"批量操作 {operation_id} 完成: {result}")
            
        except Exception as e:
            logger.error(f"批量操作 {operation_id} 失败: {e}")
        
        return operation_id


# 创建全局实例
batch_operations = WorkflowBatchOperations()